package net.fckeditor.connector;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.fckeditor.requestcycle.ThreadLocalData;
import net.fckeditor.response.GetResponse;
import net.fckeditor.response.UploadResponse;
import oh.how.easy.fck.constants.FckEditorConstants;
import oh.how.easy.fck.services.FckEditorService;
import oh.how.easy.fck.util.LegacyT5ServiceHelper;
import org.apache.tapestry5.ioc.LoggerSource;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.ApplicationGlobals;
import org.apache.tapestry5.services.HttpServletRequestFilter;
import org.apache.tapestry5.services.HttpServletRequestHandler;
import org.slf4j.Logger;

/**
 * Passes the request that are FckEditor related to the java integration lib. (<a href="http://java.fckeditor.net">java.fckeditor.net</a>) <br />
 * Also takes care of loading custom configuration from disk and returning it. (That can be defined in editor component.)
 * @author Ville Virtanen
 */
public class Tapestry5InterceptFckActivityFilter implements HttpServletRequestFilter {

    private final Pattern fileBrowserActivityPattern;
    private final Pattern configurePattern;
    private final Dispatcher dispatcher;
    private final ApplicationGlobals applicationGlobals;
    private final FckEditorService fckEditorService;
    private final Logger logger;

    public Tapestry5InterceptFckActivityFilter(ApplicationGlobals applicationGlobals, LoggerSource loggerSource, Logger logger, @Inject @Symbol(FckEditorConstants.EDITOR_CONTEXT) String location, FckEditorService fckEditorService) {
        fileBrowserActivityPattern = Pattern.compile("/assets/"+location+"/fckeditor/editor/filemanager/browser/default/fckeditor", Pattern.CASE_INSENSITIVE);
        configurePattern = Pattern.compile("/assets/"+location+"/configure", Pattern.CASE_INSENSITIVE);
        try {
            dispatcher = new Dispatcher(applicationGlobals.getServletContext());
        } catch (Exception e) {
            logger.error("Dispatcher could not be initialized", e);
            throw new RuntimeException(e);
        }
        this.applicationGlobals = applicationGlobals;
        this.logger = logger;
        this.fckEditorService = fckEditorService;
    }

    @Override
    public boolean service(HttpServletRequest request, HttpServletResponse response, HttpServletRequestHandler handler) throws IOException {

        String path = request.getServletPath();
        String pathInfo = request.getPathInfo();

        if (pathInfo != null) {
            path += pathInfo;
        }

        if (fileBrowserActivityPattern.matcher(path).matches()) {

            LegacyT5ServiceHelper.setRegistryToRequest(applicationGlobals.getServletContext(), request);
            logger.debug("Added the registry to the request.");

            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Cache-Control", "no-cache");
            PrintWriter out = response.getWriter();

            if (request.getMethod().equalsIgnoreCase("get")) {
                
                GetResponse getResponse = null;
                response.setContentType("application/xml");
                try {
                    ThreadLocalData.beginRequest(request);
                    getResponse = dispatcher.doGet(request);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    /*
                     * call this method to prevent detached requests or else the request
                     * will probably never be garbage collected and will fill your
                     * memory
                     */
                    ThreadLocalData.endRequest();
                }

                out.print(getResponse);

            } else {

                UploadResponse uploadResponse = null;
                response.setContentType("text/html");

                try {
                    ThreadLocalData.beginRequest(request);
                    uploadResponse = dispatcher.doPost(request);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    /*
                     * call this method to prevent detached requests or else the request
                     * will probably never be garbage collected and will fill your
                     * memory
                     */
                    ThreadLocalData.endRequest();
                }

                out.print(uploadResponse);

            }
            
            out.flush();
            out.close();

            return true;
        } else if (configurePattern.matcher(path).matches()) {

            String id = request.getParameter("id");
            String conf = fckEditorService.getEditorConfiguration(id);
            
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/plain");

            PrintWriter out = response.getWriter();
            out.print(conf);
            out.flush();
            out.close();

            return true;
        }

        return handler.service(request, response);
    }

}